Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use custom iterators to speed up inflow_ids and friends #830

Merged
merged 2 commits into from
Nov 27, 2023
Merged

Use custom iterators to speed up inflow_ids and friends #830

merged 2 commits into from
Nov 27, 2023

Conversation

visr
Copy link
Member

@visr visr commented Nov 26, 2023

@Huite mentioned the performance of medium-sized models regressed recently, so I looked into it a bit, doing some profiling. I saw a lot of time was spent on finding the in- and outneighbors of flow. This changed quite a bit in #807, and whilst the API is a lot nicer, unfortunately there was also a performance regression. The profile showed allocations. This PR removes those allocations, leading to a 2x speedup for a test model, from 16s to 8s. Pre-#807 this ran in 3s however, so there is still a considerable gap to close. I don't really want to revert #807, though perhaps for flow connections we need another data structure, or some other way to speed up.

This PR changes from using a filtered array comprehension, which creates a Vector{NodeID}, to a custom iterator InNeighbors which iterates over the filtered inneighbors. This avoids allocations but otherwise returns the same result.

@SouthEndMusic
Copy link
Collaborator

@visr nice that you picked this up. Regarding the gap to close: this might be due to the dictionary to map from an edge to an index in the dense flow vector. The SparseMatrixCSC we used before does not use a dictionary internally, so I suspect we can learn something from that implementation.

@SouthEndMusic
Copy link
Collaborator

Also, get_tmp is called much more often now but I thought that is basically free

@@ -13,8 +13,8 @@ function allocation_graph_used_nodes!(p::Parameters, allocation_network_id::Int)
node_type = graph[node_id].type
if node_type in [:user, :basin]
push!(used_nodes, node_id)

elseif length(inoutflow_ids(graph, node_id)) > 2
elseif count(x -> true, inoutflow_ids(graph, node_id)) > 2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that preferable? I've assumed that length simply consumes unsized iterators, just like your code using count.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's actually not defined, a MethodError.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see :)

@visr
Copy link
Member Author

visr commented Nov 27, 2023

this might be due to the dictionary to map from an edge to an index in the dense flow vector.

This didn't show up in the profile so I think that's fast enough. Though the dict lookup to check if an edge is a flow edge did show up. This was for a model with only flow edges. get_tmp also didn't show up.

@SouthEndMusic is this ok to merge for you? I think this fixes the issue enough to make a release, we can look after into more speedups.

@visr visr requested a review from SouthEndMusic November 27, 2023 10:04
@SouthEndMusic
Copy link
Collaborator

@visr disregard my comments above, those are about #828 which I am working on at the moment.

If this works and indeed gives the required speedup it is fine by me, I would like you to walk me trough how it works this afternoon if you have time

Copy link
Collaborator

@SouthEndMusic SouthEndMusic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@visr visr merged commit b8d564b into main Nov 27, 2023
15 checks passed
@visr visr deleted the iterate branch November 27, 2023 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants